function halfInterval(start:number, end:number, func: (x: number) => number, target:number, minInterval = 0.0001) {
    var left = start, right = end;
    if (end < start)
        throw 'end must be greater than start';
    while (true) { //Math.abs(right - left) > minInterval) {
        var middle = (right + left) / 2;
        var middleValue = func(middle);
        if (Math.abs(middleValue - target) < minInterval)
            return middle;
        if (middleValue > target) { right = middle; }
        else { left = middle; };
    }
    return left;
}
function halfIntervalSearchForField(func: (input: any) => any) {
    return async function (input:any) {
        var { end = 100, targetAmount = 100, targetField = 'amount' } = input;
        if (!Array.isArray(targetAmount)) {
            targetAmount=[targetAmount,targetAmount]
        }
        var targetAmounts:any = {
            buy:targetAmount[0],
            sell:targetAmount[1]
        }
        function onDirection(direction: string) {

            var gap = halfInterval(0, end, function (g) {
                const value = func(Object.assign({}, input, { randomize: 0, gap: g }));
                return value[direction][targetField];
            }, targetAmounts[direction]);
            return func(Object.assign({}, input, { randomize: 0, gap }));
        }
        var results = ['buy', 'sell'].map(onDirection);
        return Object.assign(results[0], { gaps: [results[0].gaps[0], results[1].gaps[0]], sell: results[1].sell });
    };
}
export {halfIntervalSearchForField, halfInterval};
